package cn.hsw.component.auth.jwt;


import cn.hsw.component.auth.constant.AuthConstant;
import cn.hsw.component.core.util.Validator;
import cn.hsw.component.redis.RedisUtil;
import cn.hsw.manage.permission.service.PermissionService;
import cn.hsw.manage.role.service.RoleService;
import cn.hsw.manage.user.entity.User;
import cn.hsw.manage.user.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * jwt realm
 * @author 李子木
 */
public class JwtRealm extends AuthorizingRealm {
    @Autowired
    UserService userService;
    @Autowired
    RoleService roleService;
    @Autowired
    PermissionService permissionService;

    @Autowired
    RedisUtil redisUtil;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        String token = principalCollection.toString();
        String phone = JwtUtil.getPhone(token);
        if(Validator.isEmpty(phone)){
            throw new IncorrectCredentialsException("token无效");
        }
        User user = userService.selectUserByPhone(phone);
        if(Validator.isEmpty(user)){
            throw new UnknownAccountException("用户不存在或已删除");
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if(Validator.isNotEmpty(user)){
            /*角色*/
            Set<String> roleCodeSet = roleService.getRoleCodeSet(user.getPid());
            info.addRoles(roleCodeSet);
            /*权限*/
            Set<String> permissionsSet = permissionService.getPermissionsSet(user.getPid());
            info.addStringPermissions(permissionsSet);
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        /*身份认证*/
        String token = (String) authenticationToken.getCredentials();
        String phone = JwtUtil.getPhone(token);
        if(Validator.isEmpty(phone)){
            throw new IncorrectCredentialsException(AuthConstant.TOKEN_EXIST);
        }
        User user = userService.selectUserByPhone(phone);
        if(Validator.isEmpty(user)){
            throw new UnknownAccountException(AuthConstant.USER_NOT_FOUND);
        }
        boolean verify = JwtUtil.verify(token, user.getPhone(), user.getSalt());
        if(!verify){
            throw new IncorrectCredentialsException(AuthConstant.TOKEN_EXIST);
        }
        boolean expire = redisUtil.hasKey(AuthConstant.TOKEN_REDIS_KEY + token);
        if(!expire){
            throw new IncorrectCredentialsException(AuthConstant.TOKEN_TIME_OUT);
        }
        redisUtil.expire(AuthConstant.TOKEN_REDIS_KEY + token,AuthConstant.TOKEN_EXPIRE_TIME);
        return new SimpleAuthenticationInfo(token,token,getName());
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }
}
